package com.conduit.agent;

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.sikuli.script.Screen;

import com.conduit.commands.prototype.AbstractCommand;
import com.conduit.comnands.CopyFileCommand;
import com.conduit.comnands.DownloadFileCommand;
import com.conduit.comnands.GetRegistryValueCommand;
import com.conduit.comnands.GetValueFromFileCommand;
import com.conduit.comnands.GetValueFromWebCommand;
import com.conduit.comnands.ExecuteFileCommand;
import com.conduit.comnands.SikuliStartScreenCapturingCommand;
import com.conduit.comnands.SikuliStopScreenCapturingCommand;
import com.conduit.comnands.SleepCommand;
import com.conduit.comnands.UndefinedCommand;
import com.conduit.comnands.ValidateFileExistsCommand;
import com.conduit.comnands.ValidateRegistryCommand;
import com.conduit.comnands.ValidateRegistryKeyExistsCommand;
import com.conduit.comnands.ValidateValueFromFileCommand;
import com.conduit.comnands.ValidateValueFromWebCommand;
import com.conduit.enums.ResultCode;

public class Agent {

	final Screen s = new Screen();
	HashMap<String, AbstractCommand> commands = new HashMap<String, AbstractCommand>();
	HashMap<String, String> runProperties = new HashMap<String, String>();
	AbstractCommand currentCommand;

	public Agent() {
		commands.put("execute file", new ExecuteFileCommand());
		commands.put("get registry value", new GetRegistryValueCommand());
		commands.put("validate registry", new ValidateRegistryCommand());
		commands.put("validate value from file",
				new ValidateValueFromFileCommand());
		commands.put("validate registry key exists",
				new ValidateRegistryKeyExistsCommand());
		commands.put("validate value from web",
				new ValidateValueFromWebCommand());
		commands.put("get value from web", new GetValueFromWebCommand());
		commands.put("get value from file", new GetValueFromFileCommand());
		commands.put("validate file exists", new ValidateFileExistsCommand());
		commands.put("download file", new DownloadFileCommand());
		commands.put("sleep", new SleepCommand());
		SikuliStartScreenCapturingCommand stratCmd = new SikuliStartScreenCapturingCommand();
		stratCmd.setS(s);
		commands.put("start screen capturing", stratCmd);
		SikuliStopScreenCapturingCommand stopCmd = new SikuliStopScreenCapturingCommand();
		stopCmd.setScreen(s);
		commands.put("stop screen capturing", stopCmd);
		commands.put("copy file", new CopyFileCommand());

	}

	public void executeCommand(String command) {
		String commandName = command.split("\\s{2,}")[0].toLowerCase();
		try {
			currentCommand = commands.get(commandName);
			command = replaceArgumentsPlaceHolders(command);
			currentCommand.executeWithArgs(command);
			if (currentCommand.isReturnValue()) {
				runProperties.put(
						currentCommand.getResult().split(" is a ")[0],
						currentCommand.getResult().split(" is a ")[1]);
			}
		} catch (NullPointerException e) {
			currentCommand = new UndefinedCommand();
			currentCommand.setResult("Could not find command name");
			currentCommand.setResultCode(ResultCode.Error);
		}
	}

	public String report(String machineIP) {
		return(String.format(
				"%s, %s, %s, %s",
				machineIP, currentCommand.getCommandName(),
				currentCommand.getResult(), currentCommand.getResultCode()));
	}

	public String replaceArgumentsPlaceHolders(String command) {
		Matcher matcher = Pattern.compile(".*?\\$\\{(.*?)\\}").matcher(command);
		while (matcher.find()) {
			String value = runProperties.get(matcher.group(1));
			if (value != null) {
				command = command.replace("${" + matcher.group(1) + "}", value);
			} // TODO add a report if the parameter was not found.
		}
		return command;
	}

}
